<template>
  <el-table
    :show-summary="showSummary.length ? true : false"
    :summary-method="getSummaries"
    class="tableRowClassName"
    :data="tableData"
    v-loading="loading"
    style="width: 100%"
    border
    :cell-style="{ textAlign: 'center' }"
    @selection-change="handleSelectionChange"
    @row-click="rowClick"
    :max-height="maxHeight"
    :row-class-name="tableRowClassName"
    @sort-change="sortTableFun"
    :header-cell-class-name="handleHeaderClass"
    :highlight-current-row="true"
    :header-cell-style="headerCellStyle"
    ref="multipleTable"
  >
    <el-table-column
      v-if="checked"
      type="selection"
      align="center"
      width="55"
      fixed
    >
    </el-table-column>
    <el-table-column
      v-if="showIndex"
      align="center"
      type="index"
      label="序号"
      :index="indexMethod"
      width="70"
      fixed
    >
    </el-table-column>
    <el-table-column
      v-for="(item, index) in titleObj"
      :width="item.width"
      :min-width="item.minWidth"
      :fixed="index == 0 ? 'left' : item.fixed"
      :key="item.prop"
      align="center"
      :prop="item.prop"
      :label="item.label"
      :sortable="item.sortable"
      :show-overflow-tooltip="!item.noToolTip"
    >
      <!-- 这里是自定义头部，如果titleObj 传递了 tooltip 参数，表格头部能有提示信息 -->
      <template slot="header" slot-scope="scope">
        <div v-if="item.tooltip" style="display: inline-block">
          <el-tooltip
            class="item"
            effect="dark"
            :content="item.tooltip"
            placement="top-start"
          >
            <span>{{ item.label }}<i class="el-icon-question"></i> </span>
          </el-tooltip>
        </div>
        <div v-else style="display: inline-block">
          {{ item.label }}
        </div>
      </template>
      <template slot-scope="{ row }">
        <span v-if="item.type === 'img'" style="cursor: pointer">
          <el-image
            style="width: 60px; height: 60px"
            :src="getImgUrl(row[item.prop])"
            :preview-src-list="[getImgUrl(row[item.prop])]"
          >
            <div slot="error" class="image-slot">
              <i class="el-icon-picture-outline" style="font-size: 60px"></i>
            </div>
          </el-image>
        </span>
        <span v-else-if="item.type === 'textImg'" style="cursor: pointer">
          <el-image
            style="width: 60px; height: 60px; vertical-align: middle"
            :src="getImgUrl(row[item.image])"
            :preview-src-list="[getImgUrl(row[item.image])]"
          >
            <div slot="error" class="image-slot">
              <i class="el-icon-picture-outline" style="font-size: 60px"></i>
            </div>
          </el-image>
          <span>{{ row[item.prop] }}</span>
        </span>
        <span v-else-if="item.type === 'radio'">
          <el-switch
            :value="row[item.prop]"
            active-color="#13ce66"
            inactive-color="#ff4949"
            @change="switchChange(row, item.prop)"
          >
          </el-switch>
        </span>
        <span v-else-if="item.type === 'color'">
          <span
            v-if="
              item.colorArr &&
              item.colorArr.find((aaa) => aaa.name == row[item.prop])
            "
          >
            <span
              v-for="iii in item.colorArr"
              :key="iii.name"
              :style="{ color: iii.color }"
              >{{ row[item.prop] == iii.name ? iii.name : "" }}</span
            >
          </span>
          <span v-else> {{ row[item.prop] }}</span>
        </span>
        <span
          v-else-if="!item.noToolTip"
          style="overflow: hidden; white-space: nowrap; text-overflow: ellipsis"
        >
          {{ row[item.prop] }}
        </span>
        <span v-else>
          {{ row[item.prop] }}
        </span>
      </template>
    </el-table-column>
    <el-table-column
      align="center"
      label="操作"
      :width="operateWidth"
      :fixed="fixedRight"
      v-if="operateWidth"
    >
      <template slot-scope="scope">
        <slot :scope="scope.row">
          <!-- 外面使用插槽直接复制下面出去做事情，方法随便定义 -->
          <!-- <template v-slot="{scope}">
            <el-button @click="handleClick(scope)" type="text" size="small">123</el-button>
          </template> -->
        </slot>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
import { montageStr } from "@/utils";
export default {
  name: "ETable",
  props: {
    // 表格数据
    data: {
      type: Array,
    },
    // 是否有前面的勾选
    checked: {
      type: Boolean,
      default: false,
    },
    // 是否显示序号
    showIndex: {
      type: Boolean,
      default: true,
    },
    titleObj: {
      type: Array,
      default: () => [
        { prop: "date", label: "日期", sortable: "custom" },
        { prop: "name", label: "姓名", sortable: "custom" },
        { prop: "address", label: "地址", sortable: "custom" },
      ],
    },
    // 操作栏默认固定右侧，取值left right null
    fixedRight: {
      type: String,
      default: "right",
    },
    // 操作宽度，同时判断是否显示操作栏
    operateWidth: {
      type: String,
      default: "",
    },
    // 表格在页面呈现的高度
    height: {
      type: Number,
      default: 350,
    },
    page: {
      type: Object,
    },
    // 展示合计的列
    showSummary: {
      type: Array,
      default: () => [],
    },
    // 加载状态
    loading: {
      type: Boolean,
      default: false,
    },
    // 默认排序名字和排序顺序和长度，用于headerCellStyle方法
    sortData: {
      type: Object,
      default: () => {},
    },
  },
  watch: {
    data: {
      handler(newVal) {
        this.tableData = newVal;
      },
      immediate: true,
    },
  },
  data() {
    return {
      tableData: [],
      // 表格选中的数据
      multipleSelection: [],
      maxHeight: window.innerHeight - this.height,
      // 1.表格排序
      orderArray: [],
      countNumber: 0,
    };
  },
  mounted() {
    // 侦听窗口大小改变事件
    window.addEventListener("resize", this.getHeight);
  },
  beforeDestroy() {
    // 移除监听事件
    window.removeEventListener("resize", this.getHeight);
  },
  methods: {
    getHeight() {
      // 获取窗口高度
      this.maxHeight = window.innerHeight - this.height;
    },
    // 返回前面index的索引
    indexMethod(index) {
      if (this.page != undefined) {
        return (this.page.page - 1) * this.page.size + index + 1;
      } else {
        return index + 1;
      }
    },
    getImgUrl(url) {
      if (url) {
        return this.$store.getters.baseUrl + url;
      } else {
        return null;
      }
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
      this.$emit("batch", val);
    },
    rowClick(row) {
      this.$emit("row-click", row);
    },
    tableRowClassName({ row, rowIndex }) {
      return rowIndex % 2 == 0 ? "warning-row" : "success-row";
    },
    // 排序的方法，点击排序的时候触发 prop排序字段，order 升序 还是降序
    sortTableFun({ column, prop, order }) {
      // 2.暂时没有多个排序，先注释掉
      if (order) {
        //参与排序
        let flagIsHave = false;
        // 如果排序字段有一样的，替换排序方式
        this.orderArray.forEach((element) => {
          if (element.sortName === prop) {
            element.sortType = order;
            flagIsHave = true;
          }
        });
        // 数组没有一样的，追加进去
        if (!flagIsHave) {
          this.orderArray.push({
            sortName: prop,
            sortType: order,
          });
        }
      } else {
        //不参与排序，删除在排序数组的这个字段
        let orderIndex = 0;
        this.orderArray.forEach((element, index) => {
          if (element.sortName === prop) {
            orderIndex = index;
          }
        });
        this.orderArray.splice(orderIndex, 1);
      }
      // 把排序字段换成asc和desc，方便接口请求
      this.orderArray.forEach((item) => {
        if (item.sortType == "ascending") {
          item.sortType = item.sortType.substring(0, 3);
        } else {
          item.sortType = item.sortType.substring(0, 4);
        }
      });
      if (this.orderArray.length == 0) {
        this.$emit("sortFun", "");
      } else {
        this.$emit(
          "sortFun",
          JSON.parse(JSON.stringify(montageStr(this.orderArray)))
        );
      }
    },
    // 3.表格排序多选的方法
    handleHeaderClass({ column }) {
      this.orderArray.forEach((element) => {
        if (column.property === element.sortName) {
          if (element.sortType == "asc") {
            // column.order=element.sortType
            column.order = "ascending";
          } else if (element.sortType == "desc") {
            column.order = "descending";
          } else {
            column.order = "";
          }
        }
      });
    },
    // 合计方法
    getSummaries(param) {
      // columns 列， data行数据
      // console.log(this.showSummary)
      const { columns, data } = param;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = "合计";
          return;
        }
        const values = data.map((item) => Number(item[column.property]));
        if (this.showSummary.includes(column.property)) {
          sums[index] = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0);
          sums[index] = sums[index].toFixed(2);
        } else {
          sums[index] = "";
        }
      });

      return sums;
    },
    // switch 值改变事件
    async switchChange(val, prop) {
      // 旧版
      // this.$emit('switchChange', val)
      if (!val[prop]) return this.$emit("switchChange", val);
      let t = await this.$confirm("是否确认停用该数据！", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      });
      if (t) {
        this.$emit("switchChange", val);
      }
    },
    headerCellStyle({ row, column, rowIndex, columnIndex }) {
      // 如果没有默认值不执行
      if (!this.sortData) return;
      // 只有打开页面执行，所以就是打开页面表格的长度（序列号和操作栏要加上）
      if (this.countNumber == this.sortData.len) return;
      this.countNumber += 1;
      // 排序图标高亮
      this.sortData.column.forEach((item, index) => {
        if (column.property == item) {
          column.order = this.sortData.orders[index];
          if (this.sortData.orders[index] == "ascending") {
            this.orderArray.push({
              sortName: column.property,
              sortType: this.sortData.orders[index].substring(0, 3),
            });
          } else {
            this.orderArray.push({
              sortName: column.property,
              sortType: this.sortData.orders[index].substring(0, 4),
            });
          }
        } else {
          column.order = ``;
        }
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.tableRowClassName {
  // border: 1px solid #d7d7d7;
  ::v-deep .has-gutter tr .is-center {
    // 这里是表格全选按钮的样式设置
    padding-right: 5px;
  }
  ::v-deep {
    // 表格头变灰
    .el-table__header th {
      background-color: #f4f5f7;
    }
    .el-table__body tr:hover > td {
      // 改变鼠标移入样式
      background-color: #ccc;
    }
    // // 提高表格x轴的层级，不然fiexd的栏在没有数据的情况下 下面无法拖动
    // //  但是下面全部打开了就说明fixed能穿透了，那么右/左边固定的话，能穿透到底部的排序时间和固定的tooltip无法使用bug
    // .el-table__fixed,
    // .el-table__fixed-right {
    //   pointer-events: none !important;
    //   td {
    //     pointer-events: auto !important;
    //   }
    // }
    // // 因为上面设置的 pointer-events: none 会导致顶部全选和取消全选的不能点击，所以要处理
    // .el-table__fixed
    //   .el-table__fixed-header-wrapper
    //   .el-table__header
    //   thead
    //   tr
    //   th:nth-child(1) {
    //   pointer-events: auto !important;
    // }
  }
}
</style>
<style>
/* .el-table .warning-row {
    background: oldlace;
  } */

.el-table .success-row {
  /* 隔行变色的类名颜色 可查看 tableRowClassName 方法 */
  background: #fafafa;
}
</style>
